#ifndef WIDGET_H
#define WIDGET_H

#include <QtCore>
#include <QtGui>

extern "C"
{
#define UINT64_C(c)     c ## ULL
#include "libavformat/avformat.h"
#include "libavutil/avstring.h"
#include "libavutil/pixdesc.h"
#include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
#include "libavcodec/audioconvert.h"
#include "libavcodec/colorspace.h"
#include "libavcodec/opt.h"
#include "libavcodec/avfft.h"
}

class T_FPS
{
public:
    QTime m_time_line;
    double m_fps;
    int m_count;
    explicit T_FPS() : m_fps(0), m_count(0)
    {
    }
    bool wake()
    {
        if(!m_time_line.isNull()) return false;
        m_time_line.start();
        return true;
    }
    void restart()
    {
        m_count = 0;
        m_time_line.start();
    }
    void add(int a)
    {
        m_count += a;
    }
    double value()
    {
        if(m_time_line.isNull())
        {
            qDebug() << "[T_FPS.value()] warning: T_FPS.wake() was not called.";
            return 0;
        }
        else if(m_time_line.elapsed() < 1000)
        {
            return m_fps;
        }
        else
        {
            m_fps = 1000.0 * m_count / m_time_line.elapsed();
            restart();
            return m_fps;
        }
    }
};

class T_AVPicture
{
public:
    AVPicture m_av_picture;
    enum PixelFormat m_pix_fmt;
    int m_width;
    int m_height;
    int m_numBytes;
    uint8_t *m_buffer;

    explicit T_AVPicture(PixelFormat a_pix_fmt, int a_width, int a_height)
        :
        m_pix_fmt(a_pix_fmt),
        m_width(a_width),
        m_height(a_height),
        m_numBytes(0),
        m_buffer(0)
    {
        reinit();
    }
    ~T_AVPicture()
    {
        if(m_buffer) delete[] m_buffer;
    }
    void resize(int a_width, int a_height)
    {
        if(m_width==a_width && m_height==a_height) return;
        m_width = a_width;
        m_height = a_height;
        reinit();
    }
protected:
    void reinit()
    {
        int v_numBytes=avpicture_get_size(
                m_pix_fmt,
                m_width,
                m_height
                );
        //qDebug() << "[v_numBytes][m_numBytes]" << v_numBytes << m_numBytes;
        if(m_numBytes < v_numBytes)
        {
            m_numBytes = v_numBytes;
            //qDebug() << "[m_numBytes]" << m_numBytes;
            if(m_buffer) delete[] m_buffer;
            m_buffer=new uint8_t[m_numBytes];
        }
        avpicture_fill(
                &m_av_picture,
                m_buffer,
                m_pix_fmt,
                m_width,
                m_height
                );
    }
};

namespace Ui {
    class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    Ui::Widget *ui;
protected:
    AVFormatContext	*formatCtx;
    int		videoStream;
    AVCodecContext	*codecCtx;
    AVCodec		*codec;
    AVFrame		*frame;
    AVPacket	packet;
    int		frameFinished;
    QString		filename;
    int frameNo;
    QTimer m_timer;
    QImage m_displayBuffer;
    T_AVPicture *m_av_picture;
    QTime m_time_line;
    int m_drop_count;
    AVStream *m_v_stream;
    T_FPS m_fps1;
    T_FPS m_fps2;

protected slots:
    void onTimerTimeout();

protected:
    virtual void paintEvent(QPaintEvent *e)
    {
        QPainter v_p(this);
        int v_font_size = 16;
        QFont v_f("MS UI Gothic", v_font_size, QFont::Bold);
        //QFontInfo fi(v_f);
        //qDebug() << fi.fixedPitch();
        v_f.setFixedPitch(true);
        v_p.setFont(v_f);
        v_p.drawImage(QPoint(0, 0), m_displayBuffer);
        QTime v_elapsed(0, 0, 0, 0);
        v_elapsed = v_elapsed.addMSecs(m_time_line.elapsed());
        QString v_msg = QString("E=%1 F=%2 D=%3")
                        .arg(v_elapsed.toString("hh:mm:ss[zzz]"))
                        .arg(frameNo)
                        .arg(m_drop_count)
                        ;
        //[Time etc]
        int v_diff = 1;
        int v_x_off = 2;
        int v_y_off = this->height() - 4;
        v_p.setPen(Qt::white);
        v_p.drawText(QPoint(v_x_off+v_diff, v_y_off+v_diff), v_msg);
        v_p.setPen(Qt::black);
        v_p.drawText(QPoint(v_x_off, v_y_off), v_msg);
        //[FPS]
        v_x_off = 2;
        v_y_off = v_font_size + 4;
        //v_msg = QString("%1 fps").arg(m_fps);
        //v_msg = QString("%1 fps : %2 fps").arg(m_fps).arg(m_fps2.value());
        v_msg = QString("%1 fps : %2 fps")
                .arg(m_fps1.value(), 6, 'f', 2, ' ')
                .arg(m_fps2.value(), 6, 'f', 2, ' ');
        v_p.setPen(Qt::white);
        v_p.drawText(QPoint(v_x_off+v_diff, v_y_off+v_diff), v_msg);
        v_p.setPen(Qt::black);
        v_p.drawText(QPoint(v_x_off, v_y_off), v_msg);
    }
#if 0x0
    QFontDatabase fdb;
    QStringList fl = fdb.families();
    qDebug() << fl;
    ("Arial", "Arial Black", "Arial Narrow", "Batang", "BatangChe", "Book Antiqua", "Bookman Old Style", "Century", "Century Gothic", "Comic Sans MS", "Courier", "Courier New", "Dotum", "DotumChe", "Estrangelo Edessa", "FixedSys", "Franklin Gothic Medium", "Garamond", "Gautami", "Georgia", "Gulim", "GulimChe", "Gungsuh", "GungsuhChe", "Haettenschweiler", "HGP創英角ｺﾞｼｯｸUB", "HGP創英角ﾎﾟｯﾌﾟ体", "HGPｺﾞｼｯｸE", "HGS創英角ｺﾞｼｯｸUB", "HGS創英角ﾎﾟｯﾌﾟ体", "HGSｺﾞｼｯｸE", "HG丸ｺﾞｼｯｸM-PRO", "HG創英角ｺﾞｼｯｸUB", "HG創英角ﾎﾟｯﾌﾟ体", "HG正楷書体-PRO", "HGｺﾞｼｯｸE", "Impact", "Latha", "Lucida Console", "Lucida Sans Unicode", "Mangal", "Marlett", "Microsoft Sans Serif", "MingLiU", "Modern", "Monotype Corsiva", "MS Sans Serif", "MS Serif", "MS UI Gothic", "MV Boli", "Nina", "NSimSun", "OCRB", "Palatino Linotype", "PMingLiU", "Raavi", "Roman", "Script", "Shruti", "SimHei", "SimSun", "Small Fonts", "Sylfaen", "Symbol", "System", "Tahoma", "Terminal", "Times New Roman", "Trebuchet MS", "Tunga", "Verdana", "Webdings", "Wingdings", "Wingdings 2", "Wingdings 3", "ＭＳ ゴシック", "ＭＳ 明朝", "ＭＳ Ｐゴシック", "ＭＳ Ｐ明朝")
#endif

};

#endif // WIDGET_H
